﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.DomainServices.EntityFramework;
using ServerFramework.Data;
using System.ServiceModel.DomainServices.Server;
using System.Data.Objects;
using Microsoft.Practices.Unity;
using ServerFramework.DependencyInjection;

namespace ServerFramework.Domain
{
    public abstract class DomainRepositoryService<TContext> : LinqToEntitiesDomainService<TContext>, IDbContextManager
        where TContext : ObjectContext, IDbContext, new()
    {
        protected IUnityContainer Container { get; private set; }

        /// <summary>
        /// Create a child container to use THIS as the IDbContextManager implementation when resolving repositories
        /// Ensures that multiple threads / domain services can use the main container to resolve repositories and use its own instance as the IDbContextManager for the repositories they need
        /// </summary>
        /// <param name="context">The DomainServiceContext instance</param>
        public override void Initialize(DomainServiceContext context)
        {
            base.Initialize(context);

            this.Container = IoC.Current.Container.CreateChildContainer();
            this.Container.RegisterInstance<IDbContextManager>(this);

            this.Container.RegisterType(typeof(IRepository<>), typeof(BaseRepository<>));
        }

        #region IDbContextManager Members

        public IDbContext GetDbContext()
        {
            return this.ObjectContext;
        }

        #endregion

        #region Basic CRUD

        protected IQueryable<T> GetQuery<T>()
            where T : class
        {
            return this.GetRepository<T>().GetQuery();
        }

        //coming soon
        //protected ObjectQuery<T> GetQueryEx<T>(string xmlQuery)
        //{
        //    var query = GetRepository<T>().GetQuery();
        //    if (!string.IsNullOrEmpty(xmlQuery))
        //    {
        //        var filtersExpr = XmlFilters.FromXml<T>(xmlQuery).GetQueryExpression();
        //        query = query.Where(filtersExpr);
        //    }
        //    return query as ObjectQuery<T>;
        //}

        protected void Insert<T>(T entity)
            where T : class
        {
            this.GetRepository<T>().Add(entity);
        }

        protected void Update<T>(T entity)
            where T : class
        {
            this.GetRepository<T>().AttachAsModified(entity, this.ChangeSet.GetOriginal(entity));
        }

        protected void Delete<T>(T entity)
            where T : class
        {
            this.GetRepository<T>().Delete(entity);
        }

        #endregion

        protected IRepository<T> GetRepository<T>()
            where T : class
        {
            return this.Container.Resolve<IRepository<T>>();
        }
    }

}
